﻿using System;
using System.ComponentModel.Design;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.InteropServices;

using Microsoft.VisualStudio.OLE.Interop;
using Microsoft.VisualStudio.Shell;
using Microsoft.WowAddonStudio.Lua.RuntimeService.ToolWindows;
using Microsoft.WowAddonStudio.Services;

namespace Microsoft.WowAddonStudio.Lua.RuntimeService
{
	///
	/// The minimum requirement for a class to be considered a valid package for Visual Studio
	/// is to implement the IVsPackage interface and register itself with the shell.
	/// This package uses the helper classes defined inside the Managed Package Framework (MPF)
	/// to do it: it derives from the Package class that provides the implementation of the 
	/// IVsPackage interface and uses the registration attributes defined in the framework to 
	/// register itself and its components with the shell.
	/// </summary>
	[PackageRegistration(UseManagedResourcesOnly = true)]
	// A Visual Studio component can be registered under different registry roots; for instance
	// when you debug your package you want to register it in the experimental hive. This
	// attribute specifies the registry root to use if no one is provided to regpkg.exe with
	// the /root switch.
	[DefaultRegistryRoot(@"Software\Microsoft\AppEnv\9.0\Apps\WowAddonStudio")]
	// In order be loaded inside Visual Studio in a machine that has not the VS SDK installed, 
	// package needs to have a valid load key (it can be requested at 
	// http://msdn.microsoft.com/vstudio/extend/). This attributes tells the shell that this 
	// package has a load key embedded in its resources.
	[ProvideLoadKey("Standard", "1.0", "Lua Runtime Service Package", "WowAddonStudio", 102)]
	/// Provide Lua Runtime Service as a Visual Studio service
	[ProvideService(typeof (ILuaRuntimeService), ServiceName = "Lua Runtime Service")]
	// This attribute registers a tool window exposed by this package.
	// It will initially be docked at the toolbox window location.
	[ProvideToolWindow(typeof (WowBenchToolWindow), Width = 450, Height = 250, Style = VsDockStyle.Float)]
	// The Guid of the LuaRuntimeServicePackage
	[Guid(GuidStrings.LuaRuntimeServicePackage)]
	public sealed class LuaRuntimeServicePackage : Package
	{
		private WowBenchToolWindow wowBenchToolWindow;
		private IOleComponentManager componentManager;

        private uint wowBenchToolWindowComponentId;

		/// <summary>
		/// Initialize the <see cref="Package"/>.
		/// </summary>
		protected override void Initialize()
		{
			Trace.WriteLine(string.Format(CultureInfo.CurrentCulture, "Entering Initialize() of: {0}", this));

			try
			{
				base.Initialize();

				IServiceContainer serviceContainer = this;
				serviceContainer.AddService(typeof (ILuaRuntimeService), OnCreateLuaRuntimeService, true);

				InitializeWowBenchToolWindow();
				serviceContainer.AddService(typeof (WowBenchToolWindow), wowBenchToolWindow, true);
			}
			catch (Exception e)
			{
				Trace.WriteLine(e);
				throw;
			}
		}

		/// <summary>
		/// Initialize and register the <see cref="WowBenchToolWindow"/> instance.
		/// </summary>
		private void InitializeWowBenchToolWindow()
		{
			wowBenchToolWindow = (WowBenchToolWindow) FindToolWindow(typeof (WowBenchToolWindow), 0, true);
			componentManager = (IOleComponentManager) GetService(typeof (SOleComponentManager));
			if (wowBenchToolWindowComponentId == 0)
			{
				OLECRINFO[] crinfo = new OLECRINFO[1];
				crinfo[0].cbSize = (uint) Marshal.SizeOf(typeof (OLECRINFO));
				crinfo[0].grfcrf = (uint) _OLECRF.olecrfNeedIdleTime | (uint) _OLECRF.olecrfNeedPeriodicIdleTime
				                   | (uint) _OLECRF.olecrfNeedAllActiveNotifs | (uint) _OLECRF.olecrfNeedSpecActiveNotifs;
				crinfo[0].grfcadvf = (uint) _OLECADVF.olecadvfModal | (uint) _OLECADVF.olecadvfRedrawOff |
				                     (uint) _OLECADVF.olecadvfWarningsOff;
				crinfo[0].uIdleTimeInterval = 100;

				componentManager.FRegisterComponent(wowBenchToolWindow, crinfo, out wowBenchToolWindowComponentId);
			}
		}

		/// <summary>
		/// Callback function for creation <see cref="ILuaRuntimeService"/> service instance.
		/// </summary>
		/// <param name="container">The <see cref="IServiceContainer"/> parameter.</param>
		/// <param name="serviceType">The <see cref="Type"/> of the service.</param>
		/// <returns><see cref="ILuaRuntimeService"/> implementation.</returns>
		private ILuaRuntimeService OnCreateLuaRuntimeService(IServiceContainer container, Type serviceType)
		{
			if (serviceType == typeof (ILuaRuntimeService))
			    return new LuaRuntimeService(this);

			return null;
		}

		#region IDispose Members

		/// <summary>
		/// </summary>
		/// <param name="disposing"></param>
		/// <devdoc>
		/// This method will be called by Visual Studio in reponse
		/// to a package close (disposing will be true in this
		/// case).  The default implementation revokes all
		/// services and calls Dispose() on any created services
		/// that implement IDisposable.
		/// </devdoc>
		protected override void Dispose(bool disposing)
		{
			try
			{
				if (wowBenchToolWindow != null)
					wowBenchToolWindow.Dispose();

				if (componentManager != null)
					componentManager.FRevokeComponent(wowBenchToolWindowComponentId);
			}
			catch (Exception ex)
			{
				Trace.WriteLine(ex);
			}
			finally
			{
				base.Dispose(disposing);
			}
		}

		#endregion
	}
}